struct Empty;
struct Null;

trait DoubleDrop<T> {
    fn double_drop(self, _: T);
}

impl<T>    DoubleDrop<T> for Empty {
    fn double_drop(self, _: T){}
}

impl<T> DoubleDrop<T> for Null {
    fn double_drop(self, _: T) {}
}


// merge the impl to next
trait OtherDoubleDrop<T> {
    fn double_drop1(self, _: T);
}

impl<T, U> OtherDoubleDrop<T> for U {
    fn double_drop1(self, _: T) {}
}


pub fn main(){
    let empty = Empty;
    let null = Null;

    empty.double_drop(1);
    null.double_drop(1);

    let empty1 = Empty;
    let null1 = Null;
    empty1.double_drop1(null1);

    //TODO:  cast concrete type into Trait ??? for duplicated function name between traits
    //(empty1 as dyn OtherDoubleDrop<Null>).double_drop1(null1);
}
